﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Text;
using System.Web;
using System.Net;
using System.ComponentModel;
using System.IO;
using BfLib.Text;
using Newtonsoft.Json;
using System.Linq;
using Newtonsoft.Json.Linq;

namespace BfLib.Web
{

    public class HTTPClient
    {
        private int _uniqueId;

        private WebClient _client;
        //public delegate void DownloadProgressChangedEventHandler(object sender, DownloadProgressChangedEventArgs e);
        public event DownloadProgressChangedEventHandler OnDownloadProgressChanged;
        public event DownloadStringCompletedEventHandler OnDownloadStringCompleted;
        public event DownloadDataCompletedEventHandler OnDownloadDataCompleted;
        public event AsyncCompletedEventHandler OnDownloadFileCompleted;
        public event OpenReadCompletedEventHandler OnOpenReadCompleted;
        public event OpenWriteCompletedEventHandler OnOpenWriteCompleted;
        public event UploadDataCompletedEventHandler OnUploadDataCompleted;
        public event UploadFileCompletedEventHandler OnUploadFileCompleted;
        public event UploadProgressChangedEventHandler OnUploadProgressChanged;
        public event UploadStringCompletedEventHandler OnUploadStringCompleted;
        public event UploadValuesCompletedEventHandler OnUploadValuesCompleted;

        private int _oldAsyncPercent = 0, _newAsyncPercent = 0;
        //to fire event OnDownloadProgressChanged(sender, e);

        public HTTPClient()
        {
            _uniqueId = StringLib.GetCRandomNum(0, Int32.MaxValue);
            _client = new System.Net.WebClient();
                        
            _client.DownloadProgressChanged += new DownloadProgressChangedEventHandler(MyDownloadProgessChanged);// new System.Net.DownloadDataCompletedEventHandler(_client);
            _client.DownloadStringCompleted += new DownloadStringCompletedEventHandler(MyDownloadStringCompleted);
            _client.DownloadDataCompleted += new DownloadDataCompletedEventHandler(MyDownloadDataCompleted);
            _client.DownloadFileCompleted += new AsyncCompletedEventHandler(MyDownloadFileCompleted);
            _client.OpenReadCompleted += new OpenReadCompletedEventHandler(MyOpenReadCompleted);
            _client.OpenWriteCompleted += new OpenWriteCompletedEventHandler(MyOpenWriteCompleted);
            _client.UploadDataCompleted += new UploadDataCompletedEventHandler(MyUploadDataCompleted);
            _client.UploadFileCompleted += new UploadFileCompletedEventHandler(MyUploadFileCompleted);
            _client.UploadProgressChanged += new UploadProgressChangedEventHandler(MyUploadProgressChanged);
            _client.UploadStringCompleted += new UploadStringCompletedEventHandler(MyUploadStringCompleted);
            _client.UploadValuesCompleted += new UploadValuesCompletedEventHandler(MyUploadValuesCompleted);
        }

        public string Get(string url, string CookieHeaderValue = null)
        {
            if (CookieHeaderValue != null)
            {
                _client.Headers.Add("Cookie", CookieHeaderValue);
            }

            return _client.DownloadString(url);
        }

        public string PostValues(string Url, NameValueCollection PostData, string CookieHeaderValue = null)
        {
            if (CookieHeaderValue != null)
            {
                _client.Headers.Add("Cookie", CookieHeaderValue);
            }

            byte[] resp = _client.UploadValues(Url, PostData);
            return System.Text.ASCIIEncoding.ASCII.GetString(resp);// Encoding.ASCII.GetBytes(resp);
        }

        public bool DownloadFile(string Url, string FileName, string CookieHeaderValue = null)
        {
            if (CookieHeaderValue != null)
            {
                _client.Headers.Add("Cookie", CookieHeaderValue);
            }

            //_client.Headers.Add("byte-range", "0-100");
            _client.DownloadFile(Url, FileName);
            return false;
        }

        public void DownloadFileAsync(string Url, string DirectoryName, string CookieHeaderValue = null)
        {
            Uri uri = new Uri(Url);
            _oldAsyncPercent = 0;
            _newAsyncPercent = 0;
            string fileName = DirectoryName + Path.GetFileName(Url);

            if (CookieHeaderValue != null)
            {
                _client.Headers.Add("Cookie", CookieHeaderValue);
            }
            _client.DownloadFileAsync(uri, fileName);
        }

        public void CancelAsync()
        {
            _client.CancelAsync();
        }

        public void DownloadFileAsync(string Url, string DirectoryName, Object CallbackToken, string CookieHeaderValue = null)
        {
            Uri uri = new Uri(Url);
            string fileName = DirectoryName + Path.GetFileName(Url);

            if (CookieHeaderValue != null)
            {
                _client.Headers.Add("Cookie", CookieHeaderValue);
            }
            _client.DownloadFileAsync(uri, fileName, CallbackToken);
        }

        protected void MyDownloadProgessChanged(object sender, DownloadProgressChangedEventArgs e)
        {
            _newAsyncPercent = e.ProgressPercentage;
            if (_newAsyncPercent > _oldAsyncPercent)
            {
                OnDownloadProgressChanged(sender, e);
            }

            _oldAsyncPercent = _newAsyncPercent;
        }

        protected void MyDownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
        {
            OnDownloadStringCompleted(sender, e);
        }

        protected void MyDownloadDataCompleted(object sender, DownloadDataCompletedEventArgs e)
        {
            OnDownloadDataCompleted(sender, e);
        }

        protected void MyDownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
        {
            OnDownloadFileCompleted(sender, e);
        }

        protected void MyOpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
        {
            OnOpenReadCompleted(sender, e);
        }

        protected void MyOpenWriteCompleted(object sender, OpenWriteCompletedEventArgs e)
        {
            OnOpenWriteCompleted(sender, e);
        }

        protected void MyUploadDataCompleted(object sender, UploadDataCompletedEventArgs e)
        {
            OnUploadDataCompleted(sender, e);
        }

        protected void MyUploadFileCompleted(object sender, UploadFileCompletedEventArgs e)
        {
            OnUploadFileCompleted(sender, e);
        }

        protected void MyUploadProgressChanged(object sender, UploadProgressChangedEventArgs e)
        {
            OnUploadProgressChanged(sender, e);
        }

        protected void MyUploadStringCompleted(object sender, UploadStringCompletedEventArgs e)
        {
            OnUploadStringCompleted(sender, e);
        }

        protected void MyUploadValuesCompleted(object sender, UploadValuesCompletedEventArgs e)
        {
            OnUploadValuesCompleted(sender, e);
        }

        public static string DownloadText(string url, string CookieHeaderValue = null)
        {

            try
            {
                WebClient w = new WebClient();
                if (CookieHeaderValue != null)
                {
                    w.Headers.Add("Cookie", CookieHeaderValue);
                }
                return w.DownloadString(url);
            }
            catch
            {
                throw new Exception(String.Format("Could not download text from url {0}", url));
            }
        }

        public dynamic GetJSONObect(string url)
        {
            string myJson = this.Get(url);
            return JObject.Parse(myJson);
        }

        public int UniqueId
        {
            get
            {
                return _uniqueId;
            }
        }

    }
}
